package org.JWCB.friend.manager;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import org.JWCB.common.core.constants.CacheConstants;
import org.JWCB.common.core.domain.dto.QueryDto;
import org.JWCB.common.redis.service.RedisService;
import org.JWCB.friend.domain.message.vo.MessageListItemVo;
import org.JWCB.friend.mapper.user.UserMessageTextMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
public class MessageCacheManager {


    @Autowired
    private UserMessageTextMapper userMessageTextMapper;

    @Autowired
    private RedisService redisService;


    /**
     * 获取消息列表长度
     */
    public Long getListSize(Long userId) {
        String key = getUserMsgListKey(userId);
        return redisService.getListSize(key);
    }




    /**
     * 得到消息列表缓存key
     */
    private String getUserMsgListKey(Long useId) {
        return CacheConstants.USER_MESSAGE_LIST_KEY + useId;
    }

    /**
     * 得到消息详情列表缓存key
     */
    private String getUserDetailKey(Long textId) {
        return CacheConstants.MESSAGE_DETAIL_KEY + textId;
    }

    /**
     * 刷新缓存
     */
    public void refreshCache(Long userId) {
        List<MessageListItemVo> messageListItemVos = userMessageTextMapper.selectMessageList(userId);
        String userMsgListKey = getUserMsgListKey(userId);
        if(CollectionUtil.isEmpty(messageListItemVos)) {
            // 数据库也为空,设置空值,防止缓存击穿
            redisService.leftPushForList(userMsgListKey,-1);
            return;
        }
        Set<Long> textIds = messageListItemVos.stream().map(MessageListItemVo::getTextId).collect(Collectors.toSet());
        redisService.rightPushAll(userMsgListKey,textIds);
        Map<String,MessageListItemVo> messageListItemVoMap = new HashMap<>();
        for(MessageListItemVo messageListItemVo : messageListItemVos) {
            messageListItemVoMap.put(getUserDetailKey(messageListItemVo.getTextId()),messageListItemVo);
        }
        redisService.multiSet(messageListItemVoMap);
    }


    /**
     * 从缓存中获取消息列表
     */
    public List<MessageListItemVo> getMessageList(QueryDto queryDto, Long userId) {
        int start = (queryDto.getPageNum()-1) * queryDto.getPageSize();
        int end = start + queryDto.getPageSize() - 1;
        String messageListKey = getUserMsgListKey(userId);
        List<Long> textIds = redisService.getCacheListByRange(messageListKey, start, end, Long.class);
        if(textIds.size() == 1 && textIds.get(0) == -1) {
            // 为空
            return new ArrayList<>();
        }
        List<MessageListItemVo> messageItemList = assembleMsgList(textIds);
        if(CollectionUtil.isEmpty(messageItemList)) {
            messageItemList = getMessageListByDB(queryDto,userId);
            refreshCache(userId);
        }
        return messageItemList;

    }

    /**
     * 从缓存中删除消息数据
     */
    public void delCache(Long userId,Long textId) {
        String textKey = getUserDetailKey(textId);
        redisService.deleteObject(textKey);
        String msgListKey = getUserMsgListKey(userId);
        redisService.removeForList(msgListKey,textId);
    }
    /**
     * 从数据库中获取
     */
    private List<MessageListItemVo> getMessageListByDB(QueryDto queryDto, Long userId) {

        PageHelper.startPage(queryDto.getPageNum(),queryDto.getPageSize());
        return userMessageTextMapper.selectMessageList(userId);
    }


    /**
     * 根据ids从缓存中获取msg数据
     */
    private List<MessageListItemVo> assembleMsgList(List<Long> ids) {
        if(CollectionUtil.isEmpty(ids)) {
            return null;
        }
        List<String> detailKeyList = new ArrayList<>();
        for(Long id : ids) {
            detailKeyList.add(getUserDetailKey(id));
        }
        List<MessageListItemVo> messageListItemVos = redisService.multiGet(detailKeyList, MessageListItemVo.class);
        CollUtil.removeNull(messageListItemVos);
        if(CollectionUtil.isEmpty(messageListItemVos)) {
            return null;
        }
        return messageListItemVos;
    }


}
